import ReactDOM from 'react-dom';
import {observable,action,computed, reaction} from "mobx";
import HrmBaseStore from "../../../pc4backstage/hrmComsPublic/stores/baseStore";
import {message,Button,Menu,Dropdown} from 'antd';
import {WeaLocaleProvider,WeaTools, WeaInputSearch} from 'ecCom';
import {WeaTableNew} from "comsMobx";
import * as api from "../apis/monthReport";
import find from 'lodash/find';
import findIndex from 'lodash/findIndex';
import filter from 'lodash/filter';
import has from 'lodash/has';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import difference from 'lodash/difference';
import {i18n} from '../public/i18n';
import {IEVersion} from '../util/pure-util';
import DisplaySetting from '../components/report/month4template/DisplaySetting';

const {TableStore} = WeaTableNew;
const getLabel = WeaLocaleProvider.getLabel;

class HrmAttendanceMonthReport4Template extends HrmBaseStore {
  //#region 班次浏览按钮定义
  get shiftBrowserProps(){
    return {
      browserModalProps: {
        closable: true,
      },
      closable: true,
      checkStrictly: true,
      completeParams: {},
      conditionDataParams: {},
      dataParams: {},
      destDataParams: {},
      expandfirstnode: false,
      hasAddBtn: false,
      hasAdvanceSerach: true,
      hasBorder: false,
      hideVirtualOrg: false,
      icon: "icon-coms-hrm",
      iconBgcolor: "#217346",
      idSeparator: ",",
      isAutoComplete: 1,
      isDetail: 0,
      isMultCheckbox: false,
      isSingle: false,
      linkUrl: "",
      pageSize: 10,
      quickSearchName: "serial",
      showCheckStrictly: true,
      title: "班次",
      type: "mkqshift",
      viewAttr: 2,
      customized: true,
      memorise: true
    }
  }
  //#endregion
  
  //#region 测试数据
  // storage = {
  //   displaySetting: {
  //     groups: [{
  //       groupname: 'xxx',
  //       grouplabel: '390351',
  //       options: getOptions(),
  //       value: '1,2'
  //     },{
  //       groupname: 'xxx',
  //       grouplabel: '500013',
  //       options: getOptions(),
  //       value: '3,4'
  //     }],
  //     serial: [{id: '', name: ''}, {id: '', name: ''}]
  //   },
  //   typeselect: {
  //     typeselect: '6',
  //     fromDate: '2020-03-01',
  //     toDate: '2020-03-31'
  //   },
  //   viewScope: {
  //     viewScope: '3',
  //     resourceIdObject: [
  //       {id: '690', name: '梁毅11'},
  //       {id: '137', name: 'yhm21'}
  //     ]
  //   }
  // }
  //#endregion

  //#region WeaTop属性
  @observable showHasNotAccount = false;
  @computed get isNoAccount(){return this.showHasNotAccount ? '1' : '0'}
  @observable _topButtons = [];
  @computed get topButtons(){
    return this.toJS(this._topButtons);
  }
  set topButtons(v){
    this._topButtons = v;
  }

  get getDropDownMenu(){
    return (
      <Menu ecId={`${this && this.props && this.props.ecId || ''}_Menu@hfducl`}>
        {
          [
            {
              key: 'attendancedays',
              onClickHandle: () => this.showDetail(null, 'attendancedays'),
              content: getLabel(391409, '出勤明细')
            }, {
              key: 'beLate',
              onClickHandle: () => this.showDetail(null, 'beLate'),
              content: getLabel(20088, '迟到明细')
            }, {
              key: 'leaveEearly',
              onClickHandle: () => this.showDetail(null, 'leaveEearly'),
              content: getLabel(20089, '早退明细')
            }, {
              key: 'absenteeism',
              onClickHandle: () => this.showDetail(null, 'absenteeism'),
              content: getLabel(20090, '旷工明细')
            }, {
              key: 'forgotCheck',
              onClickHandle: () => this.showDetail(null, 'forgotCheck'),
              content: getLabel(20091, '漏签明细')
            }, {
              key: 'leave',
              onClickHandle: () => this.showDetail(null, 'leave'),
              content: getLabel(20092, '请假明细')
            }, {
              key: 'businessLeave',
              onClickHandle: () => this.showDetail(null, 'businessLeave'),
              content: getLabel(20093, '出差明细')
            }, {
              key: 'officialBusiness',
              onClickHandle: () => this.showDetail(null, 'officialBusiness'),
              content: getLabel(20094, '公出明细')
            }, {
              key: 'overtimeTotal',
              onClickHandle: () => this.showDetail(null, 'overtimeTotal'),
              content: getLabel(33501, '加班明细')
            }
          ].map((m, index) => {
            return (
              <Menu.Item ecId={`${this && this.props && this.props.ecId || ''}_undefined@wz18zf@${index}`} key={m.key}>
                <div onClick={m.onClickHandle}>{m.content}</div>
              </Menu.Item>
            )
          })
        }
      </Menu>
    )
  }

  @computed get topBtnAndMenus(){
    const buttons = [], menus = [];
    const generateMenus = (i, menuName, icon, onClickHandle) => {
      menus.push({
        key: i + '',
        content: menuName,
        icon: <i className={icon}/>,
        onClick: onClickHandle,
      });
    }
    this.topButtons.map((d, i) => {
      let menuFun = d.menuFun;
      menuFun = menuFun.replace(/\([^\)]*\)/g, '');//去除小括号
      if(1 == d.isTop){
        if(d.type === "BTN_SHOW_NOACCOUNT"){
          const menuName = this.showHasNotAccount ? getLabel('31504','显示无账号人员') : getLabel('500013','不显示无账号人员');
          const icon = this.showHasNotAccount ? 'icon-coms-ShowNoAccount' : 'icon-coms-NoAccountNoDisplay';
          const iconColor = this.showHasNotAccount ? '#2DB7F5' : '#8A8A8A';
          buttons.push(
            (
              <Button ecId={`${this && this.props && this.props.ecId || ''}_Button@8o5j7v@${i}`} size="small" style={{ height: '28px' }} onClick={this.showAll} title={menuName}>
                <span>
                  <i className={icon} style={{ color: iconColor }} /> 
                </span>
              </Button>
            )
          )
          generateMenus(i, menuName, icon, this.showAll);
        }else{
          if(d.type === 'BTN_SAVE_TEMPLETE'){
            if(this.mainActiveTabKey == '0'){
              buttons.push(
                (<Button ecId={`${this && this.props && this.props.ecId || ''}_Button@mzd9a1@${i}`} type="primary" onClick={() => this[menuFun] && this[menuFun]()}>{d.menuName}</Button>)
              );
              generateMenus(i, d.menuName, d.menuIcon, () => this[menuFun] && this[menuFun]());
            }else{
              buttons.push(
                (<Button ecId={`${this && this.props && this.props.ecId || ''}_Button@ax7abj@${i}`} type="primary" onClick={() => this.doSaveTemplate()}>{getLabel(30986, '保存')}</Button>)
              );
              generateMenus('save', getLabel(30986, '保存'), this.menuIconCollection.save, () => this.doSaveTemplate());
              buttons.push(
                (<Button ecId={`${this && this.props && this.props.ecId || ''}_Button@axjqzl@${i}`} type="primary" onClick={() => this.saveTemplete(true)}>{getLabel(131623, '另存为')}</Button>)
              );
              generateMenus('saveAs', getLabel(131623, '另存为'), this.menuIconCollection.create, () => this.saveTemplete(true));
            }
          }else{
            buttons.push(
              (<Button ecId={`${this && this.props && this.props.ecId || ''}_Button@o0p637@${i}`} type="primary" onClick={() => this[menuFun] && this[menuFun]()}>{d.menuName}</Button>)
            );
            generateMenus(i, d.menuName, d.menuIcon, () => this[menuFun] && this[menuFun]());
          }
        }
      }else{
        menus.push({
          key: i + '',
          content: d.menuName,
          icon: <i className={d.menuIcon}/>,
          onClick: () => this[menuFun] && this[menuFun](),
        });
      }
      
    });
    
    buttons.push((
      <Dropdown ecId={`${this && this.props && this.props.ecId || ''}_Dropdown@25uo6g`} overlay={this.getDropDownMenu} trigger={['click']} >
        <Button ecId={`${this && this.props && this.props.ecId || ''}_Button@ojo2ai`} type='primary'>{getLabel(501537, '查看汇总数据')}</Button>
      </Dropdown>
    ));

    menus.push({
      key: menus.length.toString(),
      content: getLabel(354, '刷新'),
      icon: <i className={this.menuIconCollection['sync']}/>,
      onClick: () => this.getKQReport(this.getQueryParams())
    });

    return {
      buttons,
      dropMenuDatas: [
        ...menus
      ]
    }
  }

  @computed get topProps(){
    return {
      title: getLabel('390351','考勤汇总报表'),
      icon: <i className='icon-coms-hrm'/>,
      iconBgcolor: '#217346',
      showDropIcon: true,
      ...this.topBtnAndMenus
    }
  }
  //#endregion

  //#region WeaTab 分组信息
  @observable mainActiveTabKey = '';

  @observable _mainTabs = [];
  @computed get mainTabs(){
    return this.toJS(this._mainTabs);
  }
  set mainTabs(v){
    this._mainTabs = v;
  }

  @computed get mainTabProps(){
    const tabConfig = {
      tabs: this.mainTabs,
      keyParam: "viewCondition",
      activeTabKey: this.mainActiveTabKey,
      onTabEdit: (tabKey, action) => this.onTabEdit(tabKey, action, this.refreshMainData)
    }

    return {
      tabConfig,
      activeTabInfo: {
        activeTabKey: tabConfig.activeTabKey,
        activeTabIndex: 0
      },
      rightMenu: this.topBtnAndMenus.dropMenuDatas,
      store: this,
      tabChangeHandle: this.setActiveTab
    }
  };

  @action setActiveTab = k => {
    // this.mainActiveTabKey = k;
    this.refreshMainData(k);
    // this.initRadioGroupConfig();
  }

  @action onTabEdit = async (tabKey, action, callback) => {
    if(findIndex(this.mainTabs, {viewCondition: tabKey}) < 0) return;
		switch (action) {
			case 'remove':
				this.confirmInfo({
					content: i18n.confirm.delete(),
					onOk: async () => {
            const data = await api.deleteReportMoudle({ids: tabKey});
            if (data.status === '1') {
              message.success(i18n.message.deleteSuccess());
              callback && callback();
            } else {
              message.error(data.message);
            }
					}
				});
				break;
			default:
				break;
		}
	}
  //#endregion

  //#region 初始化数据
  @action initData = async () => {
    const menuDatas = await api.getRightMenu();
    const {btnMenu} = menuDatas || {};
    this.topButtons = btnMenu || [];
    const tabDatas = await api.getReportMoudleTabs();
    if(tabDatas.status == '1'){
      const {tabs} = tabDatas;
      const storage = {};
      this.mainTabs = tabs.map((d, i) => {
        if(i == 0) this.mainActiveTabKey = d.key;
        const {editable, key, title, moudledata} = d;
        Object.assign(storage, {[key]: (typeof(moudledata) == 'string' ? JSON.parse(moudledata) : moudledata)});
        return {
          editable: editable,
          color: "#000000",
          title: title,
          viewCondition: key
        }
      });
      this.storageStore = storage;//设置模板配置
      this.initRadioGroupConfig();
    }else{
      message.error(tabDatas.message);
    }
  }

  @action init = () => {
    this.clearData();
    this.showRadioGroup = true;
    this.initData();
  }

  @action refreshMainData = async tabKey => {
    tabKey && (this.mainActiveTabKey = tabKey);
    const tabDatas = await api.getReportMoudleTabs();
    if(tabDatas.status == '1'){
      const {tabs} = tabDatas;
      const storage = {};
      this.mainTabs = tabs.map((d, i) => {
        if(tabKey == null && i == 0) this.mainActiveTabKey = d.key;
        const {editable, key, title, moudledata} = d;
        Object.assign(storage, {[key]: (typeof(moudledata) == 'string' ? JSON.parse(moudledata) : moudledata)});
        return {
          editable: editable,
          color: "#000000",
          title: title,
          viewCondition: key
        }
      });
      this.storageStore = storage;//设置模板配置
      // tabKey && (this.mainActiveTabKey = tabKey);
      this.initRadioGroupConfig();
    }else{
      message.error(tabDatas.message);
    }
  }

  @action clearData = () => {
    this.pageIndex = 1;
    this.pageSize = 10;
    this.total = 0;
    this.radioGroupVal = {};
    this.showHasNotAccount = false;
  };
  //#endregion

  //#region radioGroup
  radioGroupVal = {};
  @observable refreshRadioGroup = new Date().getTime();
  @observable _storageStore = {};
  @computed get storageStore(){
    return this.toJS(this._storageStore);
  }
  set storageStore(v){this._storageStore = v}
  @computed get storage(){
    return this.storageStore[this.mainActiveTabKey] || {};
  }

  @observable _showRadioGroup = true;
  @computed get showRadioGroup(){return this._showRadioGroup}
  set showRadioGroup(v){
    this._showRadioGroup = v;
    setTimeout(() => {
      this.reCalculateTableHeight = new Date().getTime();  
    }, 0)
  }

  displaySetting = {}
  rangeConditions = [];
  rangeKeys = {}

  @computed get radioGroupConfig(){
    this.refreshRadioGroup;
    return {
      config: [
        this.displaySetting,
        ...this.rangeConditions
      ],
      key: new Date().getTime(),
      onChange: this.onRadioGroupChangeHandle
    }
  }

  @computed get displayColumns(){
    const {displaySetting} = this.storage;
    const {groups} = displaySetting || {};
    const columns = ['lastname'];
    try{
      groups.map(g => {
        const arr = g.value.split(',');
        columns.push(...arr);
        arr.map(k => {
          columns.push(...(get(this.cascader, k) || []));
        })
      })
    }catch(e){

    }
    return columns;
  }

  @computed get selectedSerial(){
    const {displaySetting} = this.storage;
    const {serial = []} = displaySetting || {};

    if(serial.length > 0){
      return serial.map(d => d.id).join(',');
    }else
      return '';
  }

  //获取时间范围和数据范围定义
  cascader = {};
  @action getCondition = async () => {
    const data = await api.getSearchCondition();
    if(data.status == '1'){
      const {conditions, showColumns: cascader} = data;
      this.cascader = cascader;
      this.rangeKeys = {};
      this.rangeConditions = conditions.map(condition => {
        const {domkey} = condition;
        Object.assign(this.rangeKeys, {[domkey]: []})
        let options = condition.options;
        let selectLinkageDatas = condition.selectLinkageDatas;
        Object.keys(selectLinkageDatas).map(k => {
          const {conditionType, domkey: linkdomkey} = selectLinkageDatas[k];
          this.rangeKeys[domkey].push(...linkdomkey);
          if(conditionType == 'BROWSER'){
            selectLinkageDatas[k].domkey = [...linkdomkey, `${linkdomkey[0]}Value`, `${linkdomkey[0]}Object`];
            this.rangeKeys[domkey].push(`${linkdomkey[0]}Object`);
          }
        })

        const key = domkey[0];
        const flag = has(this.storage, key);
        if(flag){
          const value = get(this.storage, key);
          const selectedKey = value[key] || '0';
          options = options.map(op => {
            return {
              ...op,
              selected: op.key === selectedKey
            }
          });
          if(has(selectLinkageDatas, selectedKey)){
            const {conditionType, domkey: linkdomkey} = selectLinkageDatas[selectedKey];
            switch(conditionType){
              case 'RANGEPICKER':
                linkdomkey.map(k => {
                  Object.assign(selectLinkageDatas[selectedKey], {
                    [k]: value[k]//selectLinkageDatas中设置与domkey同名的属性，用于显示默认值
                  })
                })
                break;
              case 'CHECKBOX':
                linkdomkey.map(k => {
                  Object.assign(selectLinkageDatas[selectedKey], {
                    value: value[k]//selectLinkageDatas中设置与domkey同名的属性，用于显示默认值
                  })
                })
                break;
              case 'BROWSER':
                selectLinkageDatas[selectedKey].browserConditionParam.replaceDatas = value[`${linkdomkey[0]}Object`];//设置浏览按钮默认值
                break;
            }
          }
        }
        return {
          ...condition,
          options,
          selectLinkageDatas
        }
      });
      this.refreshRadioGroup = new Date().getTime();
    }else{
      message.error(data.message);
    }
  }

  @action initRadioGroupConfig = () => {
    this.generateDisplaySetting();
    this.getCondition();
    this.resetScroll();
  }

  //创建显示列自定义组件
  @action generateDisplaySetting = d => {
    this.displaySetting = {
      label: getLabel('390081', '展示列'),
      domkey: ['checking'],
      labelcol: 3,
      fieldcol: 21,
      com: (
        <DisplaySetting ecId={`${this && this.props && this.props.ecId || ''}_DisplaySetting@dy0grb`} store={this} />
      )
    }
  }

  //全选事件
  @action onSelectAllChangeHandle = (v, i) => {
    const {displaySetting} = this.storage;
    const {groups} = displaySetting || {};
    try{
      if(v == 0){
        Object.assign(groups[i], {value: ''});
        this.showBrowser(false);
      }else{
        const {options} = groups[i];
        const values = options.map(op => op.key);
        Object.assign(groups[i], {value: values.join(',')});
        values.indexOf('attendanceSerial') > -1 && this.showBrowser(true);
      }
      this.storageStore = Object.assign(this.storageStore, {
        [this.mainActiveTabKey]: {
          ...this.storageStore[this.mainActiveTabKey],
          displaySetting: {
            groups
          }
        }
      })
    }catch(e){

    }
  }

  checkAttendanceSerial = (oldValue, newValue) => {
    const oldKeys = oldValue.split(',');
    const newKeys = newValue.split(',');
    const removedKeys = difference(oldKeys, newKeys);
    const addedKeys = difference(newKeys, oldKeys);
    if(addedKeys.indexOf('attendanceSerial') > -1){
      this.showBrowser(true);
    }else if(removedKeys.indexOf('attendanceSerial') > -1){
      this.showBrowser(false);
    }else{}
  }

  @action onSelectChangeHandle = (v, i, checkBrowser) => {
    const {displaySetting} = this.storage;
    const {groups} = displaySetting || {};
    try{
      this.checkAttendanceSerial(groups[i].value, v);
      // checkBrowser && this.showBrowser(v);
      Object.assign(groups[i], {value: v});
      this.storageStore = Object.assign(this.storageStore, {
        [this.mainActiveTabKey]: {
          ...this.storageStore[this.mainActiveTabKey],
          displaySetting: {
            groups
          }
        }
      })
    }catch(e){

    }
  }

  @action showBrowser = flag => {
    if(flag){
      const monitor = setInterval(() => {
        if(this.browser){
          clearInterval(monitor);
          this.browser.openModal();
        }
      }, 500);
    }else{
      this.onBrowserChangeHandle('','', []);
    }
  }

  @action onRadioGroupChangeHandle = params => {
    this.radioGroupVal = params;
    try{
      let storage = this.storage;
      Object.keys(params).map(k => delete storage[k]);
      Object.keys(this.rangeKeys).map(k => {
        delete storage[k];
        const data = {[k]: params[k]};
        const linkKeys = this.rangeKeys[k];
        linkKeys.map(k => {
          const v = params[k];
          !isEmpty(v) && Object.assign(data, {
            [k]: Array.isArray(v) ? v.map(obj => ({id: obj.id, name: obj.name})) : v
          })
        })
        Object.assign(storage, {
          [k]: data
        })
      })
      
      this.storageStore = Object.assign(this.storageStore, {
        [this.mainActiveTabKey]: storage
      });

      if (params.typeselect === '6' && (params.fromDate === '' || params.toDate === ''))
        return;
      switch (params.viewScope) {
        case '1':
          if (params.subCompanyId == null || params.subCompanyId == '') {
            return;
          }
          break;
        case '2':
          if (params.departmentId == null || params.departmentId == '') {
            return;
          }
          break;
        case '3':
          if (params.resourceId == null || params.resourceId == '') {
            return;
          }
          break;
      }

      this.getKQReport(this.getQueryParams());
    }catch(e){

    }
  }

  @action setBrowser = dom => this.browser = dom;

  @action onBrowserChangeHandle = (ids, names, datas) => {
    try{
      const {displaySetting} = this.storage;
      Object.assign(displaySetting, {serial: datas.map(d => ({id:d.id, name: d.name}))});
      this.storageStore = Object.assign(this.storageStore, {
        [this.mainActiveTabKey]: {
          ...this.storageStore[this.mainActiveTabKey],
          displaySetting
        }
      })
      this.getKQReport(this.getQueryParams());
    }catch(e){

    }
  }
  //#endregion

  //#region 报表数据
  shortWeekdays = this.getLocale().lang.format.veryShortWeekdays;

  @action showAll = () => {
    this.showWeaLoadingGlobal();
    this.showHasNotAccount = !this.showHasNotAccount;
    this.getKQReport(this.getQueryParams());
    this.hideWeaLoadingGlobal();
  }
  //#endregion

  //#region 保存模板
  @observable createTemplateDialogVisible = false;
  @computed get createTemplateDialogProps(){
    let buttons = [<Button ecId={`${this && this.props && this.props.ecId || ''}_Button@ziw78g`} type='primary' op='save' onClick={() => this.doCreateTemplate()}>{i18n.label.save()}</Button>];
    return {
      ...this.dialogPropsDef,
      title: getLabel('18418','存为模板'),
      style: {
        width: 500,
        height: 90
      },
      onCancel: () => {
        this.createTemplateDialogVisible = false;
      },
      visible: this.createTemplateDialogVisible,
      buttons,
      moreBtn: {datas: this.convertToMenus(buttons)},
      key: new Date().getTime()
    }
  }

  @action saveTemplete = async (saveAs = false) => {
    this.showWeaLoadingGlobal();
    const data = await api.getReportMoudleForm();
    if(data.status == 1){
      this.setFormData("createTemplateForm", data.formField);
      if(this.formTarget.createTemplateForm.isFormInit)
        this.createTemplateDialogVisible = true;
    }else{
      message.error(data.message);
    }
    this.hideWeaLoadingGlobal();
  }

  @action doCreateTemplate = async () => {
    this.showWeaLoadingGlobal();

    const form = this.formTarget.createTemplateForm,
    formParams = form.getFormParams();
    const f = await form.validateForm();
    if (f.isValid) {
      const params = {...formParams};
      Object.assign(params, {moudledata: JSON.stringify(this.storage)});
      const data = await api.saveReportMoudle(params);
      if (data.status === "1") {
        message.success(i18n.message.saveSuccess());
        this.createTemplateDialogVisible = false;
        this.refreshMainData(data.id || this.mainActiveTabKey);
      } else {
        message.error(data.message);
      }
      this.hideWeaLoadingGlobal();
    } else {
      this.hideWeaLoadingGlobal();
      f.showErrors();
      const fields = this.formTarget.createTemplateForm.fieldMap;
      [...Object.keys(fields)].map(k => {
        const e = this.formTarget.createTemplateForm.getError(fields[k]);
        if (e != null && e != "") {
          console && console.debug(e);
        }
      });
      this.showError = new Date().getTime();
    }
}

  @action doSaveTemplate = async () => {
    this.showWeaLoadingGlobal();

    const params = {id: this.mainActiveTabKey, moudledata: JSON.stringify(this.storage)};
    const data = await api.saveReportMoudle(params);
    message.success(data.status == 1 ? i18n.message.saveSuccess() : data.message);
    this.hideWeaLoadingGlobal();
  }
  
  //#endregion

  //#region 报表数据
  @observable pageIndex = 1;
  @observable pageSize = 10;
  @observable total = 0;

  @observable _tableColumns = [];
  @computed get tableColumns(){
    let columns = this.toJS(this._tableColumns);
    columns = filter(columns, column => this.displayColumns.find(v => v.toLowerCase() == column.dataIndex.toLowerCase()))
    columns.map((c, i) => {
      // if (IEVersion() == -1 && ['lastname', 'subcompany', 'department'].indexOf(c.dataIndex) > -1 && this.checkDisplay(c.dataIndex))
      // const fixedColumns = ['lastname', 'subcompany', 'department'];
      // const flag = fixedColumns.find(v => v == c.dataIndex.toLowerCase()) && this.displayColumns.find(v => v == c.dataIndex.toLowerCase());// && this.displayColumns.find(v => fixedColumns.find(c => v == c.toLowerCase());
      // if ((flag || c.dataIndex == 'lastname') && columns.lenth > 1)
      //   c.fixed = 'left';
      // else
      //   c.fixed = null;

      const {
        title,
        unit,
        isSystem
      } = c;
      if (unit != null && unit != '') {
        c.title = (
          <div className='rSpan2' title={`${title}(${unit})`}>
            <div className='title'>{title}</div>
            <div className='unit'>({unit})</div>
          </div>
        )
      }
      c.render = (text, record, index) => {
        if(isSystem != 1 && Number(text) == 0)
          return <div>{text}</div>;
        if (c.dataIndex == 'lastname') {
          return <a href={`javaScript:openhrm(${record.resourceId});`} onClick={e => window.pointerXY(e)} title={text}><div className='text-elli'>{text}</div></a>;
        } else if (c.dataIndex == 'subcompany') {
          return <a onClick={() => window.open(`/spa/hrm/engine.html#/hrmengine/organization?showTree=false&isView=1&type=subcompany&id=${record.subcompanyId}`)} title={text}><div className='text-elli'>{text}</div></a>;
        } else if (c.dataIndex == 'department') {
          return <a onClick={() => window.open(`/spa/hrm/engine.html#/hrmengine/organization?showTree=false&isView=1&type=department&id=${record.departmentId}`)} title={text}><div className='text-elli'>{text}</div></a>;
        } else if (c.dataIndex == 'jobtitle') {
          return <a onClick={() => window.open(`/spa/hrm/engine.html#/hrmengine/posts?id=${record.jobtitleId}`)} title={text}><div className='text-elli'>{text}</div></a>;
        } else if (c.dataIndex == 'workcode') {
          return <a href={`javaScript:openhrm(${record.resourceId});`} onClick={e => window.pointerXY(e)} title={text}><div className='text-elli'>{text}</div></a>;
        } else
          return c.showDetial == '1' ? <a onClick={() => this.showDetail(record.resourceId, c.dataIndex, c.type, record[c.dataIndex])} title={text}><div className='text-elli'><div dangerouslySetInnerHTML={{ __html: text }} /></div></a> : <div dangerouslySetInnerHTML={{ __html: text }} />;
      }

      this.renderCol(c);
    });

    return columns;
  }
  set tableColumns(v){this._tableColumns = v}

  @computed get tableWidth(){
    return this.tableColumns.reduce((sum, current) => sum + current.width, 0);
  }

  @observable _tableDatas = [];
  @computed get tableDatas(){return this.toJS(this._tableDatas)}
  set tableDatas(v){this._tableDatas = v}

  @computed get tableProps(){
    return {
      key: new Date().getTime(),
      columns: this.tableColumns,
      dataSource: this.tableDatas,
      bordered: true,
      ref: dom => this.domRef.table = dom,
      scroll: {
        x: this.tableWidth,
        y: this.tableHeihgt - 200
      },
      pagination: {
        total: this.total,
        current: this.pageIndex,
        pageSize: this.pageSize,
        showQuickJumper: true,
        pageSizeOptions: [10, 20, 50, 100],
        showSizeChanger: true,
        showTotal: (total) => {
            return `${i18n.label['18609']()} ${total} ${i18n.label['30690']()}`;
        },
        onShowSizeChange: (current, pageSize) => {
            this.getKQReport(this.getQueryParams(current, pageSize));
        },
        onChange: (current) => {
            this.getKQReport(this.getQueryParams(current));
        }
    }
    }
  }

  @observable _holidays = [];
  @computed get holidays(){return this.toJS(this._holidays)}
  set holidays(v){this._holidays = v}

  domRef = {};
  @observable _reCalculateTableHeight = new Date().getTime();
  @computed get reCalculateTableHeight(){return this._reCalculateTableHeight}
  set reCalculateTableHeight(v){this._reCalculateTableHeight = v}
  @computed get tableHeihgt(){
    this.reCalculateTableHeight;
    const topHeight = this.domRef.top && this.domRef.top.refs.content ? this.domRef.top.refs.content.clientHeight : 0;
    const tabHeight = this.domRef.tab ? $(this.domRef.tab)[0].clientHeight : 0;
    const h = topHeight - tabHeight;
    return h <= 0 ? 0 : h;
  }

  @action setDomRef = (dom, type) => {
    dom && Object.assign(this.domRef, {[type]: dom}) && setTimeout(() => this.reCalculateTableHeight = new Date().getTime(), 500);
  }

  @action getQueryParams = (pageIndex, pageSize) => {
    this.pageIndex = pageIndex || 1;
    const params = {
      pageIndex: this.pageIndex,
      ...this.radioGroupVal,
      isNoAccount: this.isNoAccount,
      attendanceSerial: this.selectedSerial
    }
    pageSize && Object.assign(params, {pageSize});
    return params;
  }

  @action renderCol = column => {
    column.children && column.children.map(c => {
      const {
        title,
        unit,
        dataIndex,
        isSystem
      } = c;
      const date = this.moment(dataIndex, 'YYYY-MM-DD');
      if (c.isCalendar == '1') {
        const weekDay = date.day();
        const holidayInfo = find(this.toJS(this.holidays), {
          date: date.format('YYYY-MM-DD')
        });
        c.title = (
          <div title={c.dataIndex} className='date' style={{ color: weekDay == 6 || weekDay == 0 || holidayInfo != null ? "red" : "#000" }}>
            <div className='weekday text-elli'>{this.shortWeekdays[weekDay]}</div>
            <div className='day'>{date.date()}</div>
            {
                holidayInfo != null &&
                <img src={`/hrm/hrm_e9/images/${['1','3'].indexOf(holidayInfo.type) > -1 ? 'rest' : 'work'}.png`} />
            }
          </div>
        );
      } else if (unit != null && unit != '') {
        c.title = (
          <div className='rSpan1' title={`${title}(${unit})`}>
            <div className='title'>{title}</div>
            <div className='unit'>({unit})</div>
          </div>
        )
      }
      c.render = (text, record, index) => {
        let rs = text;
        if (typeof(text) == 'object') {
          rs = text.text;
        }
        const {
          dataIndex
        } = c, {
          resourceId
        } = record;
        if(isSystem != 1 && Number(text) == 0)
          return <div>{text}</div>;
        if (c.isCalendar == '1')
          return <a onClick={() => this.showSignDetail({resourceId,kqDate:dataIndex})} title={rs}><div className='text-elli'><div dangerouslySetInnerHTML={{ __html: rs }} /></div></a>
        return c.showDetial == '1' ? <a onClick={() => this.showDetail(record.resourceId, c.dataIndex, c.type, record[c.dataIndex], c.isCalendar)} title={rs}><div className='text-elli'><div dangerouslySetInnerHTML={{ __html: rs }} /></div></a> : <div dangerouslySetInnerHTML={{ __html: rs }} />;
      }
      this.renderCol(c);
    })
  }

  @action getKQReport = async params => {
    this.showWeaLoadingGlobal();
    const data = await api.getKQReport({data: JSON.stringify(params)});
    if(data.status == 1 || data.status == null){
      const {columns, datas, holidays} = data;
      this.holidays = holidays;
      this.tableDatas = [...datas];
      this.tableColumns = columns;
      this.pageIndex = data.pageindex;
      this.pageSize = data.pagesize || 10;
      this.total = data.count;

      this.resetScroll();
    }else{
      message.error(data.message);
    }
    this.hideWeaLoadingGlobal();
  }

  @action resetScroll = () => {
    let dom, d;
    if(this.domRef.table){
        dom = ReactDOM.findDOMNode(this.domRef.table);
        if(dom){
          try{
            d = $(dom).find('.ant-table-scroll').find('.ant-table-body');
            d.scrollTop(0) && d.scrollLeft(0);
          }catch(e){
          }
        }
        
    }
  }

  @action reportFormat = () => {
    this.confirmInfo({
      content:getLabel('510381', '重新计算时会以当前用户所在考勤组重新计算考勤情况，如果期间有用户调整过所在考勤组，可能会造成历史数据错误，请谨慎操作！'),
      onOk: async () => {
        this.showWeaLoadingGlobal();
        const data = await api.formatData({data: JSON.stringify(this.getQueryParams())});
        if(data.status == '1'){
          message.success(i18n.message.opSuccess());
          this.getKQReport(this.getQueryParams());
        }else{
          message.error(data.message);
        }
        this.hideWeaLoadingGlobal();
      }
    });
  }
  //#endregion

  //#region 明细数据
  @observable detailTable = new TableStore();
  @observable _detailParams = {};
  @computed get detailParams(){return this.toJS(this._detailParams)}
  set detailParams(v){this._detailParams = v}
  
  @observable _detailDialogVisible = false;
  @computed get detailDialogVisible(){return this._detailDialogVisible}
  set detailDialogVisible(v){this._detailDialogVisible = v}
  @observable detailDialogTitle = '';
  @observable _detailDialogHeight = 600;
  @computed get detailDialogHeight(){return this._detailDialogHeight}
  set detailDialogHeight(v){this._detailDialogHeight = v}

  @computed get detailDialogProps(){
    let buttons = !this.isSignDetailData ? [<Button ecId={`${this && this.props && this.props.ecId || ''}_Button@4amkq2`} type='primary' op='export' onClick={() => this.detailTable.exportAll()}>{i18n.label.export()}</Button>] : [];
    const hasScroll = this.isSignDetailData;
    return {
      ...this.dialogPropsDef,
      title: this.detailDialogTitle,
      hasScroll,
      style: {
        width: 1000,
        height: this.detailDialogHeight
      },
      onCancel: () => {
        this.detailDialogVisible = false;
      },
      visible: this.detailDialogVisible,
      buttons,
      moreBtn: {datas: this.convertToMenus(buttons)}
    }
  }

  @observable detailActiveTabKey = '';

  @observable _detailTabs = [];
  @computed get detailTabs(){
    return this.toJS(this._detailTabs);
  }
  set detailTabs(v){
    this._detailTabs = v;
  }

  @computed get detailTabProps(){
    const tabConfig = {
      tabs: this.detailTabs,
      keyParam: "viewCondition",
      activeTabKey: this.detailActiveTabKey
    }

    return {
      tabConfig,
      activeTabInfo: {
        activeTabKey: tabConfig.activeTabKey,
        activeTabIndex: 0
      },
      store: this,
      tabChangeHandle: this.setDetailActiveTab,
    }
  };

  @action setDetailActiveTab = k => {
    this.detailActiveTabKey = k || '1';
    this.callDetail();
  }

  @action showDetail = async (resourceId, dataIndex, columnType, source, isCalendar) => {
    const params = {
      ...this.radioGroupVal,
      isNoAccount: this.isNoAccount,
      attendanceSerial: this.selectedSerial
    };
    resourceId && Object.assign(params, {resourceId});
    isCalendar ? Object.assign(params, {type: source.type, date: dataIndex}) : Object.assign(params, {type: dataIndex});
    this.detailParams = params;

    const data = await api.getTabs({type: params.type});
    if (data.status === '1') {
      const {tabs: tabArr} = data;
      this.detailTabs = (tabArr || []).map(tab => {
        // tab.selected && (this.detailActiveTabKey = tab.key);
        return {
          color: "#000000",
          title: tab.title,
          viewCondition: tab.key
        }
      })
      const t = find(tabArr, {selected: true});
      const tabKey = isEmpty(t) ? null : t.key;
      this.setDetailActiveTab(tabKey);
    } else {
      message.error(data.message);
    }
  }

  @action callDetail = async () => {
    const data = await api.getKQReportDetial({...this.detailParams, tabKey: this.detailActiveTabKey});
    if(data.status == 1){
      const {dialogTitle, sessionkey} = data;
      this.detailDialogTitle = dialogTitle;
      this.detailTable = new TableStore();
      this.detailTable.getDatas(sessionkey);
      this.detailDialogVisible = true;
    }else{
      message.error(data.message);
    }
  }

  @observable isSignDetailData = false;
  disposeDetailDialog = reaction(() => this.detailDialogVisible, visible => !visible && (this.isSignDetailData = visible))

  @observable _signData = {}
  @computed get signData(){return this.toJS(this._signData)}
  set signData(v){this._signData = v}

  @action showSignDetail = async params => {
    this.isSignDetailData = true;
    
    const data = await api.getKQReportSignDetial(params);
    if(data.status == 1){
      const {userInfo, signInfo, table, dialogTitle, logList = []} = data;
      const {columns, datas} = table;
      this.signData = {userInfo, signInfo, columns, datas, logList};
      this.detailDialogVisible = true;
      this.detailDialogTitle = dialogTitle;
    }else{
      message.error(data.message);
    }
  }
  //#endregion

  //#region 导出excel
  @action exportExcel = async () => {
    this.showWeaLoadingGlobal(getLabel('500702', '导出数据中，请稍候'));
    const params = {
      ...this.getQueryParams(),
      showColumns: this.displayColumns.join(',')
    };
    const data = await api.exportExcel({data: JSON.stringify(params)});
    data.status === '1' && data.url != null && data.url.trim().length > 0 && WeaTools.downloadFile(encodeURI(data.url), "GET");
    this.hideWeaLoadingGlobal();
  }
  //#endregion 

  //#region 设置默认排序
  @observable orderSettinglDialogVisible = false;
  @computed get orderSettinglDialogProps(){
    let buttons = [<Button ecId={`${this && this.props && this.props.ecId || ''}_Button@sdo98s`} type='primary' op='export' onClick={this.saveFieldOrderDefine}>{i18n.label.save()}</Button>];
    return {
      ...this.dialogPropsDef,
      icon: 'icon-coms-Flow-setting',
      title: getLabel('389339', '默认排序设置'),
      style: {
        width: 720,
        height: 500
      },
      onCancel: () => {
        this.orderSettinglDialogVisible = false;
      },
      visible: this.orderSettinglDialogVisible,
      buttons,
      moreBtn: {datas: this.convertToMenus(buttons)}
    }
  }

  @observable _transferData = [];
  @computed get transferData(){
    const datas = this.toJS(this._transferData)
    return datas.map(data => ({
      id: data.id || data.labelId,
      name: data.name || data.title,
      sort: data.sort,
      ascOrDesc: data.ascOrDesc,
      dataIndex: data.dataIndex
    }))
  }
  set transferData(v){this._transferData = v}
  @observable _transferSelectedKeys = [];
  @computed get transferSelectedKeys(){return this.toJS(this._transferSelectedKeys)}
  set transferSelectedKeys(v){this._transferSelectedKeys = v}

  @computed get transferProps(){
    this.doFilter;
    return {
      className: 'hrm-col-set-transfer',
			leftHeader: <this.TransferHeader ecId={`${this && this.props && this.props.ecId || ''}_undefined@xukjg7`} left />,
      rightHeader: <this.TransferHeader ecId={`${this && this.props && this.props.ecId || ''}_undefined@xyb41f`} />,
      filterLeft: datas => filter(datas, data => data.name.indexOf(this.searchValue.left) > -1),
      filterRight: datas => filter(datas, data => data.name.indexOf(this.searchValue.right) > -1),
      renderItem: this.renderItem,
      renderRight: this.renderRight,
      data: this.transferData,
      selectedKeys: this.transferSelectedKeys,
      onChange: keys => this.transferSelectedKeys = keys
    }
  }

  @observable doFilter = new Date().getTime();
  searchValue = {left: '', right: ''};
  // @computed get searchValue(){return this.toJS(this._searchValue)}
  TransferHeader = props => {
    const {left} = props;
    return (
      <div className='header'>
          <span>
            {left ? getLabel('385971', "待选列名") : getLabel('385972', "已选列名")}
          </span>
          <WeaInputSearch ecId={`${this && this.props && this.props.ecId || ''}_WeaInputSearch@8lujd0`} 
            style={{width: 100, float: 'right', margin: '5px 10px 5px 0px'}}
                // value={this._searchValue[left ? 'left': 'right']}
                onSearchChange={v => this.searchValue[left ? 'left': 'right'] = v}
                onSearch={() => this.doFilter = new Date().getTime()}
            />
        </div>
    )
  }

  renderItem = item => (<div className='hrm-transfer-item'><span className='name'>{item.name}</span></div>)

  renderRight = item => {
    const {name,ascOrDesc,id} = item;
    const lbl = (ascOrDesc === 'ASC') ? getLabel('21605','正序') : getLabel('21604','倒序');
		return (
			<div className='hrm-transfer-item'>
				<span className='name'>{name}</span>
				<span className='ascOrDesc' onDoubleClick={this.stopBubble} onClick={e => this.onSortClickHandle(e, id)}>{lbl}</span>
			</div>
		)
  }
  
  stopBubble = e => {
    e.stopPropagation && e.stopPropagation();
    e.preventDefault && e.preventDefault();
  }

  @action onSortClickHandle = (e, id) => {
    this.stopBubble(e);

    const datas = this.transferData.map(item => {
      if(item.id == id)
        item.ascOrDesc = (item.ascOrDesc === 'ASC') ? 'DESC' : 'ASC';
      return item;
    })
    this.transferData = datas;
  }

  @action setOrder = async () => {
    const data = await api.getFieldOrderDefine();
    if(data.status == 1){
			const {srcdatas,destdatas} = data;
      this.transferData = [...srcdatas, ...destdatas];
      this.transferSelectedKeys = destdatas.reduce((arr, current) => [...arr, current.labelId], []);
      this.orderSettinglDialogVisible = true;
    }else{
      message.error(data.message);
    }
  }

  @computed get sortParams(){
    const params = this.transferSelectedKeys.reduce((arr, id) => {
      const data = find(this.transferData, data => data.id == id);
      !isEmpty(data) && arr.push({dataIndex: data.dataIndex, ascOrDesc: data.ascOrDesc});
      return arr;
    }, []);
    return params;
  }

  @action saveFieldOrderDefine = async () => {
    const data = await api.saveFieldOrderDefine({destdatas: JSON.stringify(this.sortParams)});
    if(data.status == 1){
      message.success(i18n.message.saveSuccess());
      this.orderSettinglDialogVisible = false;
      this.getKQReport(this.getQueryParams());
    }else{
      message.error(data.message);
    }
  }

  disposeOrderSettingDialog = reaction(() => this.orderSettinglDialogVisible, visible => !visible && (this.searchValue = {left: '', right: ''}))
  //#endregion
}

export const hrmAttendanceMonthReport4Template = new HrmAttendanceMonthReport4Template();